#pragma once

#include <iostream>
#include <sys/epoll.h>
#include <unistd.h>
#include "Log.hpp"
#include "Common.hpp"

const static int gsize = 128;

class Epoller
{
private:
    bool EventMethodCore(int fd, uint32_t events, int type)
    {
        if(type == EPOLL_CTL_DEL)
        {
            ::epoll_ctl(_epFd, EPOLL_CTL_DEL, fd, nullptr);
            return true;
        }

        struct epoll_event ev;
        ev.data.fd = fd;
        ev.events = events;
        int ret = epoll_ctl(_epFd, type, fd, &ev);

        if (ret < 0)
        {
            LOG(WARNING, "epoll_ctl error!");
            return false;
        }

        LOG(INFO, "epoll_ctl %d success!\n", fd); // TODO
        return true;
    }

public:
    Epoller()
    {
        int n = epoll_create(gsize);
        if (n < 0)
        {
            LOG(FATAL, "epoll_create error!");
            exit(EPOLL_CREAT_ERROR);
        }
        _epFd = n;

        LOG(INFO, "epoll create success, epfd: %d", _epFd);
    }

    bool AddEvents(int fd, uint32_t events)
    {
        return EventMethodCore(fd, events, EPOLL_CTL_ADD);
    }

    bool ModEvents(int fd, uint32_t events)
    {
        return EventMethodCore(fd, events, EPOLL_CTL_MOD);
    }

    bool DelEvents(int fd)
    {
        return EventMethodCore(fd, 0, EPOLL_CTL_DEL);
    }

    int Wait(struct epoll_event revs[], int num, int timeout)
    {
        return ::epoll_wait(_epFd, revs, num, timeout);
    }

    ~Epoller()
    {
        if (_epFd > 0)
            ::close(_epFd);
    }

private:
    int _epFd;
};